package org.zuel.huhuForum.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.zuel.huhuForum.component.SendMsg;
import org.zuel.huhuForum.constant.CommunityConstant;
import org.zuel.huhuForum.model.User;
import org.zuel.huhuForum.param.Event;
import org.zuel.huhuForum.service.IUserService;
import org.zuel.huhuForum.util.CommunityUtil;
import org.zuel.huhuForum.util.RedisKeyUtil;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Api(tags = "登录相关业务")
@RestController
@RequestMapping(value = "/login")
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private IUserService userService;

    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private SendMsg sendMsg;

    /**
     * 注册用户
     * @param email
     * @param passwd
     * @param username
     * @param loves
     * @return
     */
    @CrossOrigin
    @PostMapping("/register")
    @ApiOperation(value = "注册用户")
    public Map register(@RequestParam(name= "email",required = true) String email,
                        @RequestParam(name= "password",required = true) String passwd,
                        @RequestParam(name = "username",required = true) String username,
                        @RequestParam(name = "loves",required = false,defaultValue = "huhu") String loves,
                        @RequestParam(name="code",required = true) String code,
                        @RequestParam(name="kaptchaOwner",required = true)String  kaptchaOwner,
                        HttpServletRequest request) throws InvalidKeySpecException, NoSuchAlgorithmException {
        Map<String,Object>model=new HashMap<>();
        // 将验证码取出 redis
        String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
        String text= (String) redisTemplate.opsForValue().get(redisKey);
        logger.info("传入验证码："+text);
        if(!code.equals(text)){
            model.put("msg", "codeMsg");
            model.put("code", "23");
            model.put("data", "验证码错误");
            return model;
        }
        User user=new User();
        user.setPassword(passwd);
        user.setUsername(username);
        user.setEmail(email);
        user.setLoves(loves);
        Map<String, Object> map = userService.register(user);
        if (map == null || map.isEmpty()) {
            model.put("data", "注册成功!");
            model.put("code", "200");
            model.put("msg", "0");
            return model;
        } else {
            return map;
        }
    }
    /**
     * 生成验证码, 并存入 Redis
     * @param response
     */
    @CrossOrigin
    @PostMapping("/ma")
    @ApiOperation(value = "生成验证码")
    public String getKaptcha(HttpServletResponse response,
                             @RequestParam("email") String email) {
        // 生成验证码
        String text = String.valueOf((int)((Math.random()*9+1)*100000)); // 生成随机字符
        logger.info("验证码：" + text);
        // 验证码的归属者
        String kaptchaOwner = CommunityUtil.generateUUID();
        Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner);
        cookie.setMaxAge(120);
        response.addCookie(cookie);
        // 将验证码存入 redis
        String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
        redisTemplate.opsForValue().set(redisKey, text, 120, TimeUnit.SECONDS);
        Event event=new Event();
        event.setData("subject", "登录").setData("email", email).setData("time", LocalDateTime.now());
        event.setEntityType(1);
        event.setData("text",text);
        sendMsg.mailEvent(event);
        return kaptchaOwner;
    }

//    /**
//     * 验证并注册
//     */
//    @CrossOrigin
//    @PostMapping("/do")
//    @ApiOperation(value = "验证")
//    public String setKaptcha(HttpServletRequest request, @RequestParam("code") String code) {
//        String kaptchaOwner= CookieUtil.getValue(request, "kaptchaOwner");
//        // 将验证码存入 redis
//        String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
//        String text= (String) redisTemplate.opsForValue().get(redisKey);
//        if(code.equals(text)){
//            return "true";
//        }
//        return "fall";
//    }

    /**
     * 用户登录
     * @param email 用户名
     * @param password 密码
     * @param code 验证码
     * @param rememberMe 是否记住我（点击记住我后，凭证的有效期延长）
     * @return
     */
    @CrossOrigin
    @PostMapping("/login")
    @ApiOperation(value = "用户登录（登录前需邮箱验证）")
    public Map login(@RequestParam(name="email",required = true) String email,
                     @RequestParam(name="password",required = false,defaultValue ="") String password,
                     @RequestParam(name="code",required = false) String code,
                     @RequestParam(name= "rememberMe", required = false) boolean rememberMe,
                     @RequestParam(name="kaptchaOwner",required = false) String kaptchaOwner) throws InvalidKeySpecException, NoSuchAlgorithmException {
        Map<String, Object>model=new HashMap<>();
        // 凭证过期时间（是否记住我）
        int expiredSeconds = rememberMe ? CommunityConstant.REMEMBER_EXPIRED_SECONDS : CommunityConstant.DEFAULT_EXPIRED_SECONDS;
        Map<String, Object> map;
        if(password.equals("")){
            // 检查验证码
            String kaptcha = null;
            if (StringUtils.isNotBlank(kaptchaOwner)) {
                String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
                kaptcha = (String) redisTemplate.opsForValue().get(redisKey);
            }else{
                //密码为空且验证码uuid为空
                model.put("msg", "codeMsg");
                model.put("code", "23");
                model.put("data", "验证身份消息为空");
                return model;
            }
            if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) {
                model.put("msg", "codeMsg");
                model.put("code", "23");
                model.put("data", "验证码信息存在错误");
                return model;
            }
             map = userService.loginma(email, expiredSeconds);
        }else {
            // 验证用户名和密码
             map = userService.login(email, password, expiredSeconds);
        }
        if (map.containsKey("ticket")) {
//             账号和密码均正确，则服务端会生成 ticket，浏览器通过 cookie 存储 ticket
//            Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
//            cookie.setMaxAge(expiredSeconds);
//            cookie.setPath("/");
//            cookie.setHttpOnly(false);
//            cookie.setDomain("cnblogs.com");

            logger.info("ticket"+map.get("ticket"));

            User user= (User) map.get("user");

//            // 构建用户认证的结果，并存入 SecurityContext, 以便于 Spring Security 进行授权
//            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
//                   user, user.getPassword(), userService.getAuthorities(user.getId()));
//            authRequest.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//            SecurityContextHolder.getContext().setAuthentication(authRequest);

            model.put("msg", "成功");
            model.put("code", "200");
            model.put("ticket", map.get("ticket"));
            model.put("userID", user.getId());
            return model;
        }
        else {
            return map;
        }
    }

    /**
     * 用户登出
     * @return
     */
    @CrossOrigin
    @GetMapping("/logout")
    @ApiOperation(value = "用户登出")
    public String logout(HttpServletRequest request) {
        String ticket=request.getHeader("ticket");
        logger.info("logout-ticket:"+ticket);
        userService.logout(ticket);
        SecurityContextHolder.clearContext();
        return "ok!";
    }

    /**
     * 重置密码
     */
    @CrossOrigin
    @PostMapping("/resetPwd")
    @ApiOperation(value = "重置密码")
    public Map resetPwd(@RequestParam(name="email",required = true) String email,
                        @RequestParam(name="newpassword",required = true) String password,
                        @RequestParam(name="code",required = true) String code,
                        @RequestParam(name="kaptchaOwner",required = true) String kaptchaOwner,
                        HttpServletRequest request) throws InvalidKeySpecException, NoSuchAlgorithmException {
        Map<String, Object> map = new HashMap<>(4);
        String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
        String text= (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isBlank(text)) {
            map.put("msg", "codeMsg");
            map.put("code", "23");
            map.put("data", "无效验证码");
            return map ;
        } else if (!code.equals(text)) {
            map.put("msg", "codeMsg");
            map.put("code", "23");
            map.put("data", "验证码错误");
            return map ;
        }
        // 执行重置密码操作
        Map<String, Object> stringObjectMap = userService.doResetPwd(email, password);
        String emailMsg = (String) stringObjectMap.get("errMsg");
        if (StringUtils.isBlank(emailMsg)) {
            map.put("msg", "0");
            map.put("data", "重置密码成功!");
            map.put("code", "200");
        }
        return map;
    }

    @CrossOrigin
    @GetMapping("/tryget")
    @ApiOperation(value = "测试")
    public String tryit() {
        return "ok!";
    }

    @CrossOrigin
    @PostMapping("/trypost")
    @ApiOperation(value = "测试")
    public String trypost() {
        return "ok!";
    }

}
